package dbops

import (
	_ "database/sql"
	"fmt"
	"gitee.com/DengAnbang/Wefore/src/bean"
	"gitee.com/DengAnbang/Wefore/src/code"
	"gitee.com/DengAnbang/Wefore/src/push"
	"gitee.com/DengAnbang/goutils/dbutils"
	"gitee.com/DengAnbang/goutils/loge"
	"gitee.com/DengAnbang/goutils/utils"
	"strings"
)

type ProjectTreeBean struct {
	bean.TreeBean
	HeadUserId   string `json:"head_user_id"`
	HeadUserName string `json:"head_user_name"`
	ProjectId    string `json:"project_id"`
	ProjectName  string `json:"project_name"`
}

func NewProjectTreeBean(data map[string]string) ProjectTreeBean {
	return ProjectTreeBean{
		TreeBean:     bean.NewTreeBean(data),
		HeadUserId:   data["user_id"],
		HeadUserName: data["name"],
		ProjectId:    data["project_id"],
		ProjectName:  data["project_name"],
	}
}

func ProjectTreeNodeCreate(userId, nodeName, nodeParentId string) (ProjectTreeBean, error) {
	var treeBean = ProjectTreeBean{}
	treeBean.NodeName = nodeName
	treeBean.NodeParentId = nodeParentId
	var depth = 0
	if len(userId) == 0 {
		return treeBean, bean.NewErrorMessage("创建人ID不能为空")
	}
	if len(nodeName) == 0 {
		return treeBean, bean.NewErrorMessage("名称不能为空")
	}
	var projectId = ""
	if len(nodeParentId) == 0 {
		nodeParentId = "0"
	} else {
		treeParentBean, err := ProjectTreeNodeSelect(nodeParentId)
		if err != nil {
			return treeBean, err
		}
		depth = treeParentBean.Depth + 1
		projectId = treeParentBean.ProjectId
	}
	uuid := utils.NewUUID()
	if len(projectId) == 0 {
		projectId = uuid
	}
	stmtIn, err := dbConn.Prepare("INSERT INTO table_tree_project (node_id,node_name,node_parent_id,depth,project_id)VALUES(?,?,?,?,?)")
	if err != nil {
		return treeBean, err
	}
	_, err = stmtIn.Exec(uuid, nodeName, nodeParentId, depth, projectId)
	if err != nil {
		return treeBean, err
	}
	stmtIn.Close()
	treeBean.Depth = depth
	treeBean.NodeId = uuid
	if nodeParentId == "0" {
		_, _ = FileTreeNodeCreate(projectId, nodeName, "0", false)
	}
	loge.WD(bean.NewSucceedMessage(treeBean).GetJson())
	return treeBean, nil
}
func ProjectTreeNodeApplyForCreate(userId, userName, askUserId, nodeName, nodeParentId, nodeParentName string) error {
	if len(userId) == 0 {
		return bean.NewErrorMessage("创建人ID不能为空")
	}
	if len(userName) == 0 {
		return bean.NewErrorMessage("创建人名称不能为空")
	}
	if len(askUserId) == 0 {
		return bean.NewErrorMessage("审批人不能为空")
	}
	if len(nodeName) == 0 {
		return bean.NewErrorMessage("节点名称不能为空")
	}
	if len(nodeParentId) == 0 {
		return bean.NewErrorMessage("节点父ID不能为空")
	}
	if len(nodeParentName) == 0 {
		return bean.NewErrorMessage("节点父名称不能为空")
	}
	sprintf := fmt.Sprintf(`{
		"userId": "%v",
		"userName": "%v",
		"askUserId": "%v",
		"nodeName": "%v",
		"nodeParentId": "%v",
		"nodeParentName": "%v"
	}`, userId, userName, askUserId, nodeName, nodeParentId, nodeParentName)
	loge.ENullable(sprintf)
	messageBean := MessageBean{
		ToUserId:       askUserId,
		MessageType:    code.TypePushCreateWorksite,
		MessageContent: fmt.Sprintf(`%s申请在%s下添加工点:%s,点击查看!`, userName, nodeParentName, nodeName),
		MessageAppend:  sprintf,
	}
	err = MessageCreate(messageBean)
	//向审批人推送
	push.Push(askUserId, code.TypePushCreateWorksite, messageBean)
	return nil
}

//向项目中添加一个部门
func ProjectTreeNodeAddStructure(userId, projectId, structureNodeId string) error {
	if len(userId) == 0 {
		return bean.NewErrorMessage("创建人ID不能为空")
	}
	if len(projectId) == 0 {
		return bean.NewErrorMessage("名称不能为空")
	}
	if len(projectId) == 0 {
		return bean.NewErrorMessage("项目id不能为空")
	}
	if len(structureNodeId) == 0 {
		return bean.NewErrorMessage("组织机构不能为空")
	}
	treeBean, err := StructureTreeNodeSelect(structureNodeId)
	if err != nil {
		return err
	}
	projectTreeBean, err := ProjectTreeNodeSelect(projectId)
	if err != nil {
		return err
	}
	uuid := projectId + "-" + treeBean.NodeId
	stmtIn, err := dbConn.Prepare("INSERT INTO table_tree_project (node_id,node_name,node_parent_id,depth,project_id)VALUES(?,?,?,?,?)")
	if err != nil {
		return err
	}
	_, err = stmtIn.Exec(uuid, treeBean.NodeName, projectId, projectTreeBean.Depth+1, projectId)
	if err != nil {
		return err
	}
	_ = stmtIn.Close()
	return ProjectTreeUserAdd(uuid, treeBean.HeadUserId, projectId)
}

//todo 递归删除(待优化)
func ProjectTreeNodeDelete(nodeId string) error {
	if len(nodeId) == 0 {
		return bean.NewErrorMessage("节点ID不能为空")
	}
	if nodeId == "0" {
		return bean.NewErrorMessage("根节点不能为删除！")
	}
	beans, err := ProjectTreeChildNodeSelectAll(nodeId)
	if err != nil {
		return err
	}
	beans = append(beans, ProjectTreeBean{TreeBean: bean.TreeBean{NodeId: nodeId}})
	for _, v := range beans {
		stmtIn, err := dbConn.Prepare("DELETE FROM table_tree_project WHERE node_id=?")
		if err != nil {
			return err
		}
		_, err = stmtIn.Exec(v.NodeId)
		if err != nil {
			return err
		}
		stmtIn.Close()
	}
	return err
}
func ProjectTreeNodeUpdate(nodeId, nodeName, headUserId string) error {
	if len(nodeId) == 0 {
		return bean.NewErrorMessage("节点ID不能为空")
	}
	treeBean, _ := ProjectTreeNodeSelect(nodeId)
	if len(nodeName) != 0 {
		treeBean.NodeName = nodeName
	}
	if len(headUserId) != 0 {
		treeBean.HeadUserId = headUserId
	}
	stmtIn, err := dbConn.Prepare("UPDATE  table_tree_project SET node_name=?,head_user_id=? WHERE node_id=?")
	if err != nil {
		return err
	}
	_, err = stmtIn.Exec(treeBean.NodeName, treeBean.HeadUserId, nodeId)
	if err != nil {
		return err
	}
	_ = stmtIn.Close()
	return err
}

//查询单个树节点的信息
func ProjectTreeNodeSelect(nodeId string) (ProjectTreeBean, error) {
	var ProjectBean ProjectTreeBean
	stmtOut, err := dbConn.Prepare("SELECT * FROM table_tree_project WHERE node_id = ?")
	if err != nil {
		return ProjectBean, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(nodeId)
	if err != nil {
		return ProjectBean, err
	}
	defer rows.Close()
	if rows.Next() {
		var stringMap map[string]string
		stringMap, err = dbutils.GetRowsMap(rows)
		if err != nil {
			return ProjectBean, err
		}
		ProjectBean = NewProjectTreeBean(stringMap)
	}
	return ProjectBean, err
}

//查询当级所有子节点树节点的信息
func ProjectTreeChildNodeSelect(nodeId string) ([]ProjectTreeBean, error) {
	var ProjectBean = make([]ProjectTreeBean, 0)
	stmtOut, err := dbConn.Prepare("SELECT * FROM table_tree_project LEFT OUTER JOIN table_user ON table_tree_project.head_user_id=table_user.user_id WHERE node_parent_id = ?")
	if err != nil {
		return ProjectBean, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(nodeId)
	if err != nil {
		return ProjectBean, err
	}
	defer rows.Close()
	for rows.Next() {
		var stringMap map[string]string
		stringMap, err = dbutils.GetRowsMap(rows)
		if err != nil {
			return ProjectBean, err
		}
		ProjectBean = append(ProjectBean, NewProjectTreeBean(stringMap))
	}
	return ProjectBean, err
}

//查询所有子节点树节点的信息
func ProjectTreeChildNodeSelectAll(nodeId string) ([]ProjectTreeBean, error) {
	//使用递归的方法
	_, err := dbConn.Exec(`DROP FUNCTION IF EXISTS get_child_list_table_tree_project ;`)
	_, err = dbConn.Exec(`
CREATE FUNCTION  get_child_list_table_tree_project(rootId VARCHAR(64))
 RETURNS VARCHAR(1000)
DETERMINISTIC
 BEGIN
   DECLARE sTemp VARCHAR(1000);
   DECLARE sTempChd VARCHAR(1000);
   SET sTemp = '$';
   SET sTempChd = cast(rootId AS CHAR);
   WHILE sTempChd IS NOT NULL DO
     SET sTemp = concat(sTemp, ',', sTempChd);
     SELECT group_concat(node_id)
     INTO sTempChd
     FROM table_tree_project
     WHERE FIND_IN_SET(node_parent_id, sTempChd) > 0 ;
   END WHILE;
   RETURN sTemp;
 END`)
	var ProjectBean = make([]ProjectTreeBean, 0)
	if err != nil {
		return ProjectBean, err
	}
	//stmtOut, err := dbConn.Prepare("SELECT * FROM table_tree_project LEFT OUTER JOIN table_user ON table_tree_project.head_user_id=table_user.user_id  WHERE  FIND_IN_SET(node_id, get_child_list_table_tree_project(?))")
	stmtOut, err := dbConn.Prepare(`SELECT * ,
		p.node_id as node_id,
		pu.node_id as pu_node_id,
		p.node_parent_id as node_parent_id,
		pu.node_parent_id as pu_node_parent_id,
		pu.node_name as project_name,
		p.node_name as node_name 
		FROM table_tree_project p 
		LEFT OUTER JOIN table_user u ON p.head_user_id=u.user_id  
		LEFT OUTER JOIN table_tree_project pu ON p.project_id=pu.node_id  
		WHERE  FIND_IN_SET(p.node_id, get_child_list_table_tree_project(?))`)
	if err != nil {
		return ProjectBean, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(nodeId)
	if err != nil {
		return ProjectBean, err
	}
	defer rows.Close()
	for rows.Next() {
		var stringMap map[string]string
		stringMap, err = dbutils.GetRowsMap(rows)
		if err != nil {
			return ProjectBean, err
		}
		if nodeId == stringMap["node_id"] {
			continue
		}
		ProjectBean = append(ProjectBean, NewProjectTreeBean(stringMap))
	}
	return ProjectBean, err
}

//todo 这里没有判断是否存在两个表,可能存在冗余数据
//项目中添加人员
func ProjectTreeUserAdd(nodeId string, userId string, projectId string) error {
	if len(nodeId) == 0 {
		return bean.NewErrorMessage("节点ID不能为空")
	}
	userIds := strings.Split(userId, ",")
	if len(userIds) == 0 {
		//return bean.NewErrorMessage("人员ID不能为空")
		return nil
	}
	treeBean, err := ProjectTreeNodeSelect(projectId)
	if err != nil {
		return err
	}
	if len(treeBean.NodeName) == 0 {
		return bean.NewErrorMessage("项目不存在！")
	}
	stmtIn, err := dbConn.Prepare("REPLACE INTO table_tree_project_user (node_id,user_id,project_id)VALUES(?,?,?)")
	if err != nil {
		return err
	}
	for _, id := range userIds {
		if len(id) != 0 {
			_, err = stmtIn.Exec(nodeId, id, projectId)
			_ = FileTreeNodeDelete(id + "-" + projectId)
			_, _ = FileTreeNodeCreate(id+projectId, treeBean.NodeName, id+"-xmwj", false)
		}
	}
	if err != nil {
		return err
	}
	return nil
}

//把人从项目中删除
func ProjectTreeUserDelete(nodeId string, userId string, projectId string) error {
	if len(nodeId) == 0 {
		return bean.NewErrorMessage("节点ID不能为空")
	}
	userIds := strings.Split(userId, ",")
	if len(userIds) == 0 {
		//return bean.NewErrorMessage("人员ID不能为空")
		return nil
	}
	stmtIn, err := dbConn.Prepare(`DELETE FROM table_tree_project_user WHERE node_id=? and user_id=?`)
	if err != nil {
		return err
	}
	for _, v := range userIds {
		if len(v) != 0 {
			_, err = stmtIn.Exec(nodeId, v)
			_ = FileTreeNodeDelete(userId + "-" + projectId)
		}
	}
	if err != nil {
		return err
	}
	return nil
}

//查询项目树中某一节点的人员
func ProjectTreeUserSelect(nodeId string) ([]UserBean, error) {
	beans := make([]UserBean, 0)
	if len(nodeId) == 0 {
		return beans, bean.NewErrorMessage("节点ID不能为空")
	}
	stmtOut, err := dbConn.Prepare("SELECT * FROM table_tree_project_user LEFT OUTER JOIN table_user ON table_tree_project_user.user_id=table_user.user_id WHERE node_id=?")
	if err != nil {
		return beans, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(nodeId)
	if err != nil {
		return beans, err
	}
	defer rows.Close()
	for rows.Next() {
		mapStrings, err := dbutils.GetRowsMap(rows)
		if err != nil {
			return beans, err
		}
		user := *NewUserBean(mapStrings)
		beans = append(beans, user)
	}
	return beans, err
}

//查询项目树中所有的人员
func ProjectTreeUserSelectAll(projectId string) ([]UserBean, error) {
	beans := make([]UserBean, 0)
	if len(projectId) == 0 {
		return beans, bean.NewErrorMessage("项目ID不能为空")
	}
	stmtOut, err := dbConn.Prepare("SELECT * FROM table_tree_project_user LEFT OUTER JOIN table_user ON table_tree_project_user.user_id=table_user.user_id WHERE project_id=?")
	if err != nil {
		return beans, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(projectId)
	if err != nil {
		return beans, err
	}
	defer rows.Close()
	for rows.Next() {
		mapStrings, err := dbutils.GetRowsMap(rows)
		if err != nil {
			return beans, err
		}
		user := *NewUserBean(mapStrings)
		beans = append(beans, user)
	}
	return beans, err
}

//查询人员所在的项目
func ProjectTreeUserSelectProject(userId string) ([]ProjectTreeBean, error) {
	beans := make([]ProjectTreeBean, 0)
	if len(userId) == 0 {
		return beans, bean.NewErrorMessage("用户ID不能为空")
	}
	var ProjectBean = make([]ProjectTreeBean, 0)
	stmtOut, err := dbConn.Prepare(`SELECT * FROM table_tree_project_user 
LEFT OUTER JOIN table_tree_project ON table_tree_project_user.node_id=table_tree_project.node_id 
WHERE table_tree_project_user.user_id = ?`)
	if err != nil {
		return ProjectBean, err
	}
	defer stmtOut.Close()
	rows, err := stmtOut.Query(userId)
	if err != nil {
		return ProjectBean, err
	}
	defer rows.Close()
	for rows.Next() {
		var stringMap map[string]string
		stringMap, err = dbutils.GetRowsMap(rows)
		if err != nil {
			return ProjectBean, err
		}
		ProjectBean = append(ProjectBean, NewProjectTreeBean(stringMap))
	}
	return ProjectBean, err
}
